; cursor.asm
; Mouse-cursor management
;
	.include "common.inc"
	.include "global.inc"
	.include "screen.inc"
	.include "timer.inc"

	.export cur_init
	.export cur_show
	.export cur_hide
	.export cur_move_to
	.export cur_set
	.export cur_begwait
	.export cur_endwait

CURSOR_SIZE = 4
CURSOR_LINES = 12
	
	.segment "DATA"

cur_handle:	.byte $00
cur_char:	.byte $00
cur_pos_mask:
	.repeat CURSOR_SIZE*8
		.byte $00
	.endrep
cur_pos_mask2:
	.repeat CURSOR_SIZE*8
		.byte $00
	.endrep
cur_pos_bm:
	.repeat CURSOR_SIZE*8
		.byte $00
	.endrep
cur_pos_bm2:
	.repeat CURSOR_SIZE*8
		.byte $00
	.endrep

bg_table:	.res 256

cur_vis:	.byte $FF
cur_xr:		.byte $00
cur_yr:		.byte $00
cur_x:		.byte $10
cur_y:		.byte $10
cur_idx:	.byte $FF

cur_left:	.byte $00
cur_top:	.byte $00

cursor:
cur_hsx:	.res 1
cur_hsy:	.res 1
cur_bm:		.res CURSOR_LINES
cur_mask:	.res CURSOR_LINES

	CURSOR_BYTES = CURSOR_SIZE*16
	
cur_ofbuf:	.res CURSOR_BYTES

cursors:	.word cur_wait
			.word cur_arrow
			.word cur_hand
			.word cur_beam
			.word cur_cross
			.word cur_window
			.word cur_activate
			.word cur_move

	.segment "CODE"
	
cur_init:	; prepare off-screen buffer
			lda #0
			ldy #CURSOR_SIZE/2
			sta last_buf+BgBuf::top
			sta last_buf+BgBuf::left
			sty last_buf+BgBuf::width
			sty last_buf+BgBuf::height
			sty new_buf+BgBuf::width
			sty new_buf+BgBuf::height
			; prepare screen buffer
			lda #CURSOR_SIZE
			jsr sg_alloc
			sty cur_handle
			tya
			jsr sg_get_block
			sta cur_char
			; prepare background table
			ldx #0
@loop:		txa
			sta bg_table, x
			inx
			bne @loop			
			; init cursor
			lda #CURSOR_WAIT
			jsr cur_set
			rts
	
	.segment "DATA"

ch_cnt:		.byte $00
ln_cnt:		.byte $00
by_cnt:		.byte $00

last_buf:	.tag BgBuf
new_buf:	.tag BgBuf

	.segment "CODE"

cur_show:	; check if visible
			inc cur_vis
			beq @do_show
			rts
@do_show:	; prepare bitmap
			jsr prep_bm
			; get last background
			lda	#<last_buf
			ldx #>last_buf
			jsr sg_save
			; restore background at last position
			ldx #CUR_BUF_SIZE
@lprest1:	lda last_buf+BgBuf::buffer-1, x
			tay
			lda bg_table, y
			sta last_buf+BgBuf::buffer-1, x
			dex
			bne @lprest1
			; get new background
			ldx cur_left
			ldy cur_top
			stx new_buf+BgBuf::left
			sty new_buf+BgBuf::top
			lda	#<new_buf
			ldx #>new_buf
			jsr sg_save
			; restore background at new position
			ldx #CUR_BUF_SIZE
@lprest2:	lda new_buf+BgBuf::buffer-1, x
			tay
			lda bg_table, y
			sta new_buf+BgBuf::buffer-1, x
			dex
			bne @lprest2
			; save background
			lda cur_char
			clc
			adc #CUR_BUF_SIZE-1
			tay
			ldx #CUR_BUF_SIZE-1
@lpsave1:	lda new_buf+BgBuf::buffer, x
			sta bg_table, y
			dey
			dex
			bpl @lpsave1
			; prepare cursor bitmap
			lda #<cur_ofbuf
			sta reg1
			ldy #>cur_ofbuf
			sty reg1+1
			ldx #0
			stx ch_cnt
			stx ln_cnt
			stx by_cnt
@cs_cp_lo:	lda new_buf+BgBuf::buffer, x
			jsr sg_select_cell
			ldy #0
			sty ln_cnt
@cs_cp_li:	lda (reg0), y
			ldy by_cnt
			and cur_pos_mask, y
			ora cur_pos_bm, y
			sta (reg1), y
			inc ln_cnt
			inc by_cnt
			ldy ln_cnt
			cpy #16
			bne @cs_cp_li
			inc ch_cnt
			ldx ch_cnt
			cpx #4
			bne @cs_cp_lo
			; wait screen refresh
			jsr wait_refresh
			; restore background
			lda	#<last_buf
			ldx #>last_buf
			jsr sg_restore
			; copy bitmap
			lda cur_handle
			jsr sg_address
			sta reg1
			sty reg1+1
			ldy #CURSOR_BYTES-1
@cpbmlp:	lda cur_ofbuf, y
			sta (reg1), y
			dey
			bpl @cpbmlp
			; show cursor bitmap
			lda cur_handle
			ldx cur_left
			stx last_buf+BgBuf::left
			ldy cur_top
			sty last_buf+BgBuf::top
			jmp sg_show
	
cur_hide:	dec cur_vis
			rts

	.segment "DATA"

l_i:		.byte $00
l_j:		.byte $00
negm:		.byte $00

	.segment "CODE"
	
cur_move_to:; X/Y ... new position
			; calc col/row & remainder
			stx cur_x
			sty cur_y
			jsr cur_hide
			jmp cur_show

prep_bm:	ldx cur_x		; TODO: optimize for changes
			ldy cur_y
			txa
			ldx #0
			sec
			sbc cur_hsx
			bcs @pox
			ldx #%11100000
@pox:		stx negm
			tax
			lsr
			lsr
			lsr
			ora negm	; sign extension
			sta cur_left
			tya
			ldy #0
			sec
			sbc cur_hsy
			bcs @poy
			ldy #%11110000
@poy:		sty negm
			tay
			lsr
			lsr
			lsr
			lsr
			ora negm	; sign extension
			sta cur_top
			txa
			and #7
			sta cur_xr
			tya
			and #15
			sta cur_yr
			; prepare expanded mask & bitmap
			jsr clear_mask
			jsr clear_bm
			
			lda #CURSOR_LINES
			sta l_i
			ldy #0
			ldx cur_yr
@cmt_l1:		; copy
			lda cur_mask, y
			sta cur_pos_mask, x
			lda cur_bm, y
			sta cur_pos_bm, x
			; shift
			lda cur_xr
			beq @cmt_skp_sh
			sta l_j
@cmt_shl1:	sec
			ror cur_pos_mask, x
			ror cur_pos_mask2, x
			lsr cur_pos_bm, x
			ror cur_pos_bm2, x
			dec l_j
			bne @cmt_shl1
@cmt_skp_sh: inx
			iny
			dec l_i
			bne @cmt_l1
		
			rts

clear_mask:	lda #$FF
			ldx #CURSOR_SIZE*16
@cm_l1:		dex
			sta cur_pos_mask, x
			bne @cm_l1
			rts

clear_bm:	lda #$00
			ldx #CURSOR_SIZE*16
@cb_l1:		dex
			sta cur_pos_bm, x
			bne @cb_l1
			rts
	
cur_set:	cmp cur_idx
			beq @csdone
			jsr cur_hide
			sta cur_idx
			asl
			tax
			lda cursors, x
			sta reg1
			lda cursors+1, x
			sta reg1+1
			ldy #0
@cplp:		lda (reg1), y
			sta cursor, y
			iny
			cpy #2+2*CURSOR_LINES
			bne @cplp
			jsr cur_show
@csdone:	rts

	.segment "DATA"

waitcnt:	.byte $FF
curshape:	.byte 0

	.segment "CODE"

cur_begwait:
			inc waitcnt
			bne @dnbegw
			lda cur_idx
			sta curshape
			lda #CURSOR_WAIT
			jmp cur_set
@dnbegw:	rts

cur_endwait:
			dec waitcnt
			bpl @dnendw
			lda curshape
			jmp cur_set
@dnendw:	rts


	.segment "RODATA"

cur_wait:	; hsx
			.byte 3
			; hsy
			.byte 5
			; bitmap
			.byte %00000000, %01111110, %01000010, %01000010
			.byte %00100100, %00011000, %00100100, %01000010
			.byte %01000010, %01111110, %00000000, %00000000
			; mask
			.byte %00000000, %00000000, %00000000, %00000000
			.byte %00000000, %10000001, %00000000, %00000000
			.byte %00000000, %00000000, %00000000, %11111111

cur_arrow:	; hsx
			.byte 1
			; hsy
			.byte 1
			; bitmap
			.byte %00000000, %01000000, %01100000, %01110000
			.byte %01111000, %01110000, %01010000, %00001000
			.byte %00001000, %00000100, %00000100, %00000000
			; mask
			.byte %00011111, %00001111, %00000111, %00000011
			.byte %00000011, %00000011, %00000011, %00000011
			.byte %11100001, %11100001, %11110001, %11110001

cur_hand:	; hsx
			.byte 2
			; hsy
			.byte 2
			; bitmap
			.byte %00000000, %00111110, %01111110, %00111110
			.byte %00000110, %00011110, %00000110, %00011110
			.byte %00000110, %00011110, %00000110, %00000000
			; mask
			.byte %10000000, %00000000, %00000000, %00000000
			.byte %00000000, %10000000, %11000000, %11000000
			.byte %11000000, %11000000, %11000000, %11100000

cur_beam:	; hsx
			.byte 3
			; hsy
			.byte 5
			; bitmap
			.byte %00000000, %00111000, %00010000, %00010000
			.byte %00010000, %00010000, %00010000, %00010000
			.byte %00010000, %00010000, %00111000, %00000000
			; mask
			.byte %10000011, %10000011, %10000011, %11000111
			.byte %11000111, %11000111, %11000111, %11000111
			.byte %11000111, %11000111, %10000011, %10000011

cur_cross:	; hsx
			.byte 3
			; hsy
			.byte 5
			; bitmap
			.byte %00000000, %01000010, %01000010, %00100100
			.byte %00100100, %00011000, %00011000, %00100100
			.byte %00100100, %01000010, %01000010, %00000000
			; mask
			.byte %00011000, %00011000, %00000000, %00000000
			.byte %10000001, %10000001, %10000001, %10000001
			.byte %00000000, %00000000, %00011000, %00011000

cur_window:	; hsx
			.byte 3
			; hsy
			.byte 4
			; bitmap
			.byte %00000000, %01111110, %01111110, %01000010
			.byte %01000010, %01000010, %01000010, %01000010
			.byte %01111110, %00000000, %00000000, %00000000
			; mask
			.byte %00000000, %00000000, %00000000, %00000000
			.byte %00000000, %00000000, %00000000, %00000000
			.byte %00000000, %00000000, %11111111, %11111111

cur_activate:
			; hsx
			.byte 3
			; hsy
			.byte 1
			; bitmap
			.byte %00000000, %00010000, %00010000, %00101000
			.byte %00101000, %01000100, %01111100, %00000000
			.byte %00000000, %00000000, %00000000, %00000000
			; mask
			.byte %11000111, %11000111, %10000011, %10000011
			.byte %00000001, %00000001, %00000001, %00000001
			.byte %11111111, %11111111, %11111111, %11111111

cur_move:	; hsx
			.byte 3
			; hsy
			.byte 5
			; bitmap
			.byte %00000000, %00010000, %00111000, %00010000
			.byte %01010100, %11111110, %01010100, %00010000
			.byte %00111000, %00010000, %00000000, %00000000
			; mask
			.byte %11000111, %10000011, %10000011, %00000001
			.byte %00000000, %00000000, %00000000, %00000001
			.byte %10000011, %10000011, %11000111, %11111111
